#include"Eventloop.h"
#include"Logger.h"
#include"Poller.h"
#include"Channel.h"
#include<sys/eventfd.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<memory>
//防止一个线程创建多个EventLoop对象
__thread Eventloop *t_loopInThisThread=nullptr;

//定义默认的Poller,IO复用接口的超时时间
const int kPollTimeMs=10000;
int createEventfd()//创建wakeupfd用来通知睡觉的subreactor起来处理新来的channel
{
    int evtfd=::eventfd(0,EFD_NONBLOCK | EFD_CLOEXEC);
    if(evtfd<0)
    {
        LOG_FATAL("eventfd error:%d \n",errno);
    }
    return evtfd;
}

Eventloop::Eventloop()
    :looping_(false)
    ,quit_(false)
    ,callingPendingFunctors_(false)
    ,threadId_(CurrentThread::tid())
    ,poller_(Poller::newDefaultPoller(this))
    ,wakeupFd_(createEventfd())
    ,wakeupChannel_(new Channel(this,wakeupFd_))
{
    LOG_DEBUG("EventLoop created %p in thread %d \n",this,threadId_);
    if(t_loopInThisThread)
    {
        LOG_FATAL("Another EventLoop %p exists in this thread %d \n",t_loopInThisThread,threadId_);
    }
    else
    {
        t_loopInThisThread=this;
    }

    //设置wakeupfd_的事件类型以及发生该事件后的回调操作
    wakeupChannel_->setReadCallback(std::bind(&Eventloop::handleRead,this));
    //每一个eventloop都将监听wakeupchannel的EPOLLIN读事件了
    wakeupChannel_->enableReading();
}

Eventloop::~Eventloop()
{
    wakeupChannel_->disableAll();
    wakeupChannel_->remove();
    ::close(wakeupFd_);
    t_loopInThisThread=nullptr;
}

//开启事件循环,相当于调度底层poller开始事件分发器，开始监听事件
void Eventloop::loop()
{
    looping_=true;//事件循环已经开始运行
    quit_=false;//重置退出标志。确保在调用 loop() 前，退出状态是“未请求退出”。

    LOG_INFO("Eventloop &p start looping \n",this);

    while(!quit_)
    {
        activeChannels_.clear();
        pollReturnTime_=poller_->poll(kPollTimeMs,&activeChannels_);
        for(Channel *channel:activeChannels_)//遍历发生事件的channel
        {
            //Poller能监听到哪些channel发生事件了，然后上报给Eventloop，然后通知channel处理相应的事件
            channel->handleEvent(pollReturnTime_);
        }
        //执行当前Eventloop事件循环需要处理的回调操作
        doPendingFunctors();
    }
    LOG_INFO("Eventloop %p stop looping \n",this);
    looping_=false;
}
void Eventloop::quit()
{
    quit_=true;
    if(!isInLoopThread())
    {
        wakeup();//怕在其他线程中quit
    }
}

void Eventloop::runInLoop(Functor cb)
{
    if(isInLoopThread())//在当前的loop线程中执行cb
    {
        cb();
    }
    else//在非当前线程中执行cb,就需要唤醒loop所在线程
    {
        queueInLoop(cb);
    }
}
void Eventloop::queueInLoop(Functor cb)
{
    std::unique_lock<std::mutex>lock(mutex_);
    pendingFunctors_.emplace_back(cb);

    //唤醒相应的，需要执行上面回调操作的loop的线程了，第二个是当前loop在执行回调，但是loop又有了新的回调
    if(!isInLoopThread() || callingPendingFunctors_)
    {
        wakeup();//唤醒loop所在线程
    }
}
void Eventloop::handleRead()
{
    uint64_t one =1;
    ssize_t n=read(wakeupFd_,&one,sizeof one);
    if(n!=sizeof one)
    {
        LOG_ERROR("Eventloop::handleRead() reads %lu bytes instead of 8",n);
    }
}
void Eventloop::wakeup()//用来唤醒loop所在线程的,向wakeupfd_写一个数据，wakeupchannel就发生读事件，当前loop线程就会唤醒
{
    uint64_t one=1;
    ssize_t n=write(wakeupFd_,&one,sizeof one);
    if(n!=sizeof one)
    {
        LOG_ERROR("Eventloop::wakeup() writes %lu bytes instead of 8\n",n);
    }
}
//下面这三个EventLoop的方法，用来调用poller的方法
void Eventloop::updateChannel(Channel* channel)
{
    poller_->updateChannel(channel);
}
void Eventloop::removeChannel(Channel* channel)
{
    poller_->removeChannel(channel);
}
bool Eventloop::hasChannel(Channel* channel)
{
   return  poller_->hasChannel(channel);
}
void Eventloop::doPendingFunctors()
{
    std::vector<Functor> functors;//创建一个局部变量 functors，用来临时存放要执行的任务。
    callingPendingFunctors_=true;

    {
        std::unique_lock<std::mutex> lock(mutex_);
        functors.swap(pendingFunctors_);
    }
    
    for(const Functor &functor:functors)
    {
        functor();//执行当前loop需要执行的回调
    }
    callingPendingFunctors_=false;
}